package edu.zju.gis.dldsj.utils;

import com.jcraft.jsch.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public final class SftpHelper implements Closeable {
    private static Logger logger = LogManager.getLogger(SftpHelper.class);
    private static Session session;
    private static Channel channelSftp;

    private static class InstanceHolder {
        private static SftpHelper instance;

        static {
            InputStream is = ClassLoader.getSystemResourceAsStream("sftp.properties");
            Properties settings = new Properties();
            try {
                settings.load(is);
                instance = new SftpHelper(settings.getProperty("sftp.host"),
                        Integer.parseInt(settings.getProperty("sftp.port")),
                        settings.getProperty("sftp.user"),
                        settings.getProperty("sftp.password")
                );
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static SftpHelper getInstance() {
        return SftpHelper.InstanceHolder.instance;
    }

    public SftpHelper(String host, Integer port, String user, String password) {
        try {
            JSch jsch = new JSch();
            session = jsch.getSession(user, host, port);
            session.setPassword(password);
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect(3000);
            channelSftp = session.openChannel("sftp");
            channelSftp.connect();
        } catch (JSchException e) {
            e.printStackTrace();
            logger.error("Session初始化时发生错误。");
        }
    }

    public boolean upload(String localPath, String remotePath) {
        try {
            ChannelSftp c = (ChannelSftp) channelSftp;
            String dir = remotePath.substring(0, remotePath.lastIndexOf("/"));
            mkDir(dir);
            c.put(localPath, remotePath);
            logger.info(String.format("文件[%s]上传成功。", localPath));
            channelSftp.disconnect();
            return true;
        } catch (SftpException e) {
            e.printStackTrace();
            logger.error(String.format("文件[%s]上传失败，Put发生错误。", localPath));
            channelSftp.disconnect();
            return false;
        }
    }

    public void mkDir(String dir) throws SftpException {
        ChannelSftp d = (ChannelSftp) channelSftp;
        d.cd("/");
        String[] folders = dir.split("/");
        for (int i = 0; i < folders.length; i++) {
            if (folders[i].length() > 0) {
                try {
                    d.cd(folders[i]);
                } catch (SftpException e) {
                    d.mkdir(folders[i]);
                    d.cd(folders[i]);
                }
            }
        }
    }

    public String getHome() {
        ChannelSftp e = (ChannelSftp) channelSftp;
        try {
            return e.getHome();
        } catch (SftpException e1) {
            return "GetHomeFailed";
        }
    }

    public void close() {
        if (channelSftp != null && channelSftp.isConnected())
            channelSftp.disconnect();
        if (session != null && session.isConnected())
            session.disconnect();
    }
}
